package cn.wolfcode.shiro;

import cn.wolfcode.domain.Employee;
import cn.wolfcode.domain.Role;
import cn.wolfcode.mapper.EmployeeMapper;
import cn.wolfcode.mapper.PermissionMapper;
import cn.wolfcode.mapper.RoleMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("crmRealm")
public class CRMRealm extends AuthorizingRealm {
    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    //获取认证信息
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户名(用户输入的)
        String username = (String) token.getPrincipal();
        //去数据库查询
        Employee emp = employeeMapper.selectByName(username);
        //不存在返回null(shiro会返回异常)
        if (emp == null) {
            return null;
        }else if (!emp.isState() && !emp.isAdmin()){
            //判断账号状态(超管除外),要是冻结就返回账号异常给登陆捕获(百度查shiro常见异常)
            throw new DisabledAccountException();
        }

        //存在则去验证密码(利用用户名加盐)
        return new SimpleAuthenticationInfo(emp, emp.getPassword(),
                ByteSource.Util.bytes(emp.getName()) , this.getName());
    }
    //private  int num=0;
    //获取授权信息
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /*System.out.println("======================================================" +
                "========================================================"+ ++num);*/
        //创建一个空的授权信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登陆的用户的信息
        Employee currentUser = (Employee) SecurityUtils.getSubject().getPrincipal();
        //是超级管理员,则设置角色为admin和用通配符设置所有权限
        if(currentUser.isAdmin()){
            info.addRole("admin");
            info.addStringPermission("*:*");
            return info;
        }
        //查询角色集合
        List<Role> roleList = roleMapper.selectByEmpId(currentUser.getId());
        //定义一个角色的sn集合
        List<String> roleSnList = new ArrayList<>();
        //转换成角色的sn集合
        for (Role role : roleList) {
            roleSnList.add(role.getSn());
        }
        //查询权限表达式集合
        List<String> permissions = permissionMapper.selectByEmpId(currentUser.getId());
        //把登陆的用户的,角色的sn集合,权限表达式集合添加到授权信息
        info.addRoles(roleSnList);
        info.addStringPermissions(permissions);
        //返回给shiro用于判断权限
        return info;
    }


    //在该 Realm 中使用指定的凭证匹配器来完成密码匹配的操作
    @Autowired
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }
}
